#include<stack>
#include<list>
#include<map>
#include<vector>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include "secd.h"

Value* make_integer(int n) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varInt;
    val->value.intValue = n;
    return val;
}

Value* make_float(float n) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varFloat;
    val->value.floatValue = n;
    return val;
}

Value* make_cfunc(c_func n) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varFunc;
    val->value.cfuncValue = n;
    return val;
}

Value* make_lambda(int n) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varLambda;
    val->value.funcValue = n;
    std::cout << "make lambda position:" << n << std::endl;
    return val;
    //    std::cout << "make lambda pointer:" << val << std::endl;
}

Value* make_char(char n) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varChar;
    val->value.charValue = n;
    return val;
}

Value* make_bool(int n) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varBool;
    val->value.intValue = n;
    return val;
}

Value* make_nil() {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varNil;
    return val;
}

Value* make_symbol(char *n, int len) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varSymbol;
    val->value.strValue = n;
    val->length = len;
    return val;
}

Value* make_list(std::vector<Value*> *n) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varList;
    val->value.listValue = n;
    return val;
}

Value* make_string(char *n, int len) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varString;
    val->value.strValue = n;
    val->length = len;
    return val;
}

Value* make_name(char *n, int len) {
    Value* val = (Value *) malloc(sizeof (Value));
    val->type = varName;
    val->value.strValue = n;
    val->length = len;
    return val;
}

int is_integer(Value* v) {
    return v->type == varInt;
}

int is_char(Value* v) {
    return v->type == varChar;
}

int is_string(Value* v) {
    return v->type == varString;
}

int is_symbol(Value* v) {
    return v->type == varSymbol;
}

int is_name(Value* v) {
    return v->type == varName;
}

int is_float(Value* v) {
    return v->type == varFloat;
}

int is_lambda(Value* v) {
    return v->type == varLambda;
}

int is_cfunc(Value* v) {
    return v->type == varFunc;
}

int is_nil(Value* v) {
    return v->type == varNil;
}

int is_list(Value* v) {
    return v->type == varList;
}

int is_bool(Value* v) {
    return v->type == varBool;
}

int int_value(Value* v) {
    return v->value.intValue;
}

float float_value(Value* v) {
    return v->value.floatValue;
}

char* string_value(Value* v) {
    return v->value.strValue;
}

char* name_value(Value* v) {
    return v->value.strValue;
}

char char_value(Value* v) {
    return v->value.charValue;
}

int bool_value(Value* v) {
    return v->value.intValue;
}

char* symbol_value(Value* v) {
    return v->value.strValue;
}

c_func cfunc_value(Value* v) {
    return (c_func) v->value.cfuncValue;
}

int lambda_value(Value* v) {
    return v->value.funcValue;
}

std::vector<Value*>* list_value(Value* v) {
    return v->value.listValue;
}

void ins_add(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    //    std::cout << "add."  << std::endl;
    Value *args = v->stack->top();
    v->stack->pop();
    Value *tmp = NULL;
    int is_ret_float = 0;

    int int_ret = 0;
    float float_ret = 0;

    if (!is_list(args)) {
        std::cout << "add args error 1." << std::endl;
        exit(3);
    }
    std::vector<Value *> *arglist = list_value(args);
    int size = arglist->size();
    //    std::cout << "args size:" << size << std::endl;
    //    std::cout << "argslist pointer:"<< arglist << std::endl;
    for (int i = 0; i < size; ++i) {
        tmp = (Value *) arglist->at(i);
        //        arglist->pop_back();
        //        std::cout << "Value pointer:"<< tmp << std::endl;
        //        std::cout << "Value type:"<< tmp->type << std::endl;
        if (i == 0) {
            if (is_integer(tmp)) {
                int_ret = int_value(tmp);
                float_ret = int_value(tmp);
            } else if (is_float(tmp)) {
                is_ret_float = 1;
                float_ret = float_value(tmp);
            } else {
                std::cout << "add args error 2." << std::endl;
                exit(3);
            }
        } else {
            if (is_integer(tmp)) {
                int_ret += int_value(tmp);
                float_ret += int_value(tmp);
            } else if (is_float(tmp)) {
                is_ret_float = 1;
                float_ret += float_value(tmp);
            } else {
                std::cout << "add args error 3." << std::endl;
                exit(3);
            }
        }
    }
    if (is_ret_float == 1) {
        v->stack->push(make_float(float_ret));
    } else {
        v->stack->push(make_integer(int_ret));
    }
}

void ins_mul(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *args = v->stack->top();
    v->stack->pop();
    Value *tmp = NULL;
    int is_ret_float = 0;

    int int_ret = 0;
    float float_ret = 0;

    if (!is_list(args)) {
        std::cout << "mul args error 1." << std::endl;
        exit(3);
    }
    std::vector<Value *> *arglist = list_value(args);
    int size = arglist->size();
    for (int i = 0; i < size; ++i) {
        tmp = (Value *) arglist->at(i);
        if (i == 0) {
            if (is_integer(tmp)) {
                int_ret = int_value(tmp);
                float_ret = int_value(tmp);
            } else if (is_float(tmp)) {
                is_ret_float = 1;
                float_ret = float_value(tmp);
            } else {
                std::cout << "mul args error 2." << std::endl;
                exit(3);
            }
        } else {
            if (is_integer(tmp)) {
                int_ret *= int_value(tmp);
                float_ret *= int_value(tmp);
            } else if (is_float(tmp)) {
                is_ret_float = 1;
                float_ret *= float_value(tmp);
            } else {
                std::cout << "mul args error 3." << std::endl;
                exit(3);
            }
        }
    }
    if (is_ret_float == 1) {
        v->stack->push(make_float(float_ret));
    } else {
        v->stack->push(make_integer(int_ret));
    }
}

void ins_div(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *args = v->stack->top();
    v->stack->pop();
    Value *tmp = NULL;
    int is_ret_float = 0;

    int int_ret = 0;
    float float_ret = 0;

    if (!is_list(args)) {
        std::cout << "mul args error 1." << std::endl;
        exit(3);
    }
    std::vector<Value *> *arglist = list_value(args);
    int size = arglist->size();
    for (int i = 0; i < size; ++i) {
        tmp = (Value *) arglist->at(i);
        if (i == 0) {
            if (is_integer(tmp)) {
                int_ret = int_value(tmp);
                float_ret = int_value(tmp);
            } else if (is_float(tmp)) {
                is_ret_float = 1;
                float_ret = float_value(tmp);
            } else {
                std::cout << "mul args error 2." << std::endl;
                exit(3);
            }
        } else {
            if (is_integer(tmp)) {
                int_ret /= int_value(tmp);
                float_ret /= int_value(tmp);
            } else if (is_float(tmp)) {
                is_ret_float = 1;
                float_ret /= float_value(tmp);
            } else {
                std::cout << "mul args error 3." << std::endl;
                exit(3);
            }
        }
    }
    if (is_ret_float == 1) {
        v->stack->push(make_float(float_ret));
    } else {
        v->stack->push(make_integer(int_ret));
    }
}

void ins_sub(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *args = v->stack->top();
    v->stack->pop();
    Value *tmp = NULL;
    int is_ret_float = 0;

    int int_ret = 0;
    float float_ret = 0;

    if (!is_list(args)) {
        std::cout << "mul args error 1." << std::endl;
        exit(3);
    }
    std::vector<Value *> *arglist = list_value(args);
    int size = arglist->size();
    for (int i = 0; i < size; ++i) {
        tmp = (Value *) arglist->at(i);
        if (i == 0) {
            if (is_integer(tmp)) {
                int_ret = int_value(tmp);
                float_ret = int_value(tmp);
            } else if (is_float(tmp)) {
                is_ret_float = 1;
                float_ret = float_value(tmp);
            } else {
                std::cout << "mul args error 2." << std::endl;
                exit(3);
            }
        } else {
            if (is_integer(tmp)) {
                int_ret -= int_value(tmp);
                float_ret -= int_value(tmp);
            } else if (is_float(tmp)) {
                is_ret_float = 1;
                float_ret -= float_value(tmp);
            } else {
                std::cout << "mul args error 3." << std::endl;
                exit(3);
            }
        }
    }
    if (is_ret_float == 1) {
        v->stack->push(make_float(float_ret));
    } else {
        v->stack->push(make_integer(int_ret));
    }
}

void ins_nil(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    v->stack->push(make_nil());
}

void ins_cons(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *item = v->stack->top();
    v->stack->pop();
    Value *list = v->stack->top();
    v->stack->pop();
    if (is_list(list)) {
        list->value.listValue->push_back(item);
        v->stack->push(list);
    } else if (is_nil(list)) {
        std::vector<Value *> *tmp = new std::vector<Value *>;
        tmp->push_back(item);
        v->stack->push(make_list(tmp));
        //        free(list);
    } else {
        std::cout << "cons error." << std::endl;
        exit(2);
    }
}

void ins_def(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *val = v->stack->top();
    v->stack->pop();
    Value *name = v->stack->top();
    v->stack->pop();
    if (is_name(name)) {
        std::string n = string_value(name);
        v->globalEnv->insert(std::pair<std::string, Value*>(n, val));
    } else {
        std::cout << "define error." << std::endl;
        exit(2);
    }
}

void ins_le(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *right = v->stack->top();
    v->stack->pop();
    Value *left = v->stack->top();
    v->stack->pop();
    if (is_integer(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(int_value(left) <= int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(int_value(left) <= float_value(right)));
        } else {
            std::cout << "<= error." << std::endl;
            exit(9);
        }
    } else if (is_float(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(float_value(left) <= int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(float_value(left) <= float_value(right)));
        } else {
            std::cout << "<= error." << std::endl;
            exit(9);
        }
    } else {
        std::cout << "<= error." << std::endl;
        exit(9);
    }
}

void ins_ge(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *right = v->stack->top();
    v->stack->pop();
    Value *left = v->stack->top();
    v->stack->pop();
    if (is_integer(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(int_value(left) >= int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(int_value(left) >= float_value(right)));
        } else {
            std::cout << ">= error." << std::endl;
            exit(9);
        }
    } else if (is_float(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(float_value(left) >= int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(float_value(left) >= float_value(right)));
        } else {
            std::cout << ">= error." << std::endl;
            exit(9);
        }
    } else {
        std::cout << ">= error." << std::endl;
        exit(9);
    }
}

void ins_gt(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *right = v->stack->top();
    v->stack->pop();
    Value *left = v->stack->top();
    v->stack->pop();
    if (is_integer(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(int_value(left) > int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(int_value(left) > float_value(right)));
        } else {
            std::cout << "> error." << std::endl;
            exit(9);
        }
    } else if (is_float(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(float_value(left) > int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(float_value(left) > float_value(right)));
        } else {
            std::cout << "> error." << std::endl;
            exit(9);
        }
    } else {
        std::cout << "> error." << std::endl;
        exit(9);
    }
}

void ins_lt(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *right = v->stack->top();
    v->stack->pop();
    Value *left = v->stack->top();
    v->stack->pop();
    if (is_integer(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(int_value(left) < int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(int_value(left) < float_value(right)));
        } else {
            std::cout << "< error." << std::endl;
            exit(9);
        }
    } else if (is_float(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(float_value(left) < int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(float_value(left) < float_value(right)));
        } else {
            std::cout << "< error." << std::endl;
            exit(9);
        }
    } else {
        std::cout << "< error." << std::endl;
        exit(9);
    }
}

void ins_eq(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *right = v->stack->top();
    v->stack->pop();
    Value *left = v->stack->top();
    v->stack->pop();
    if (is_integer(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(int_value(left) == int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(int_value(left) == float_value(right)));
        } else {
            std::cout << "= error." << std::endl;
            exit(9);
        }
    } else if (is_float(left)) {
        if (is_integer(right)) {
            v->stack->push(make_bool(float_value(left) == int_value(right)));
        } else if (is_float(right)) {
            v->stack->push(make_bool(float_value(left) == float_value(right)));
        } else {
            std::cout << "= error." << std::endl;
            exit(9);
        }
    } else {
        std::cout << "= error." << std::endl;
        exit(9);
    }
}

void ins_sel(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *val = v->stack->top();
    v->stack->pop();
    DumpItem* d = (DumpItem *) malloc(sizeof (DumpItem));
    int left = *((int *) (v->code + v->IP));
    int right = *((int *) (v->code + v->IP + sizeof (int) +left));
    if (is_nil(val)) {
        d->IP = v->IP + sizeof (int) * 2 + left + right;
        v->IP = v->IP + sizeof (int) *2 + left;
    } else if (is_bool(val) && !bool_value(val)) {
        d->IP = v->IP + sizeof (int) * 2 + left + right;
        v->IP = v->IP + sizeof (int) *2 + left;
    } else {
        d->IP = v->IP + sizeof (int) * 2 + left + right;
        v->IP = v->IP + sizeof (int);
    }
    v->dump->push(d);
}

void ins_join(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    DumpItem* d = v->dump->top();
    v->dump->pop();
    if (d != NULL) {
        v->IP = d->IP;
    } else {
        std::cout << "join error." << std::endl;
        exit(8);
    }
}

void ins_ldi(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    int n = *((int *) (v->code + v->IP));
    v->IP += sizeof (int);
    v->stack->push(make_integer(n));
}

void ins_ldf(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    int n = *((int *) (v->code + v->IP));
    Value *r = make_lambda(v->IP + sizeof (int));
    v->IP += sizeof (int) +n;
    r->Env = new std::vector<void*>;
    if(v->environment->size() > 0){
        for (size_t i =0; i < v->environment->size(); i ++) {
            r->Env->push_back(v->environment->at(i));
        }
    }
    v->stack->push(r);
}

void ins_rtn(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    Value *ret = v->stack->top();
    v->stack->pop();
    DumpItem* d = v->dump->top();
    v->dump->pop();
    if (d == NULL) {
        std::cout << "RTN DUMP error." << std::endl;
        exit(5);
    }
//    for (int i = 0; i < (v->environment->size() - d->environment); ++i) {
//        v->environment->pop_back();
//    }
    delete v->environment;
    v->environment = d->environment;
    for (int i = 0; i < (v->stack->size() - d->stack); ++i) {
        v->stack->pop();
    }
    v->IP = d->IP;
    v->stack->push(ret);
    free(d);
}

void ins_ap(void *vm) {
    std::cout << "AP." << std::endl;
    SecdVm *v = (SecdVm *) vm;
    Value *func = v->stack->top();
    if (!is_lambda(func)) {
        std::cout << "ap lambda error type:" << func->type << std::endl;
        exit(7);
    }
    v->stack->pop();
    Value *arglist = v->stack->top();
    v->stack->pop();
    DumpItem* d = (DumpItem *) malloc(sizeof (DumpItem));
    d->IP = v->IP;
    d->environment = v->environment;
    d->stack = v->stack->size();
    std::cout << "IP1:" << v->IP << std::endl;
    v->IP = func->value.funcValue;
    std::cout << "IP2:" << v->IP << std::endl;
    v->dump->push(d);
    if (!is_list(arglist)) {
        std::cout << "arglist is not a list.:" << std::endl;
        exit(6);
    }
    std::vector<void*> *Env = new std::vector<void*>;
    if(func->Env->size() > 0){
        for (size_t i =0; i < func->Env->size(); i ++) {
            Env->push_back(func->Env->at(i));
        }
    }
    v->environment = Env;
    v->environment->push_back(list_value(arglist));

}


void ins_rap(void *vm) {
    std::cout << "RAP." << std::endl;
    SecdVm *v = (SecdVm *) vm;
    Value *func = v->stack->top();
    if (!is_lambda(func)) {
        std::cout << "ap lambda error type:" << func->type << std::endl;
        exit(7);
    }
    v->stack->pop();
    Value *arglist = v->stack->top();
    v->stack->pop();
    DumpItem* d = (DumpItem *) malloc(sizeof (DumpItem));
    d->IP = v->IP;
    d->environment = v->environment;
    d->stack = v->stack->size();
    std::cout << "IP1:" << v->IP << std::endl;
    v->IP = func->value.funcValue;
    std::cout << "IP2:" << v->IP << std::endl;
    v->dump->push(d);
    if (!is_list(arglist)) {
        std::cout << "arglist is not a list.:" << std::endl;
        exit(6);
    }
    std::vector<void*> *Env = new std::vector<void*>;
    
    if(func->Env->size() > 0){
        Value *last = (Value *)func->Env->at(func->Env->size()-1);
        if(is_nil(last)){
            last->type=varList;
            last->value.listValue = arglist->value.listValue;
        }
        for (size_t i =0; i < func->Env->size(); i ++) {
            Env->push_back(func->Env->at(i));        
        }
    }
    v->environment = Env;
    v->environment->push_back(list_value(arglist));

}


void ins_tap(void *vm) {
    std::cout << "TAP." << std::endl;
    SecdVm *v = (SecdVm *) vm;
    Value *func = v->stack->top();
    if (!is_lambda(func)) {
        std::cout << "ap lambda error type:" << func->type << std::endl;
        exit(7);
    }
    v->stack->pop();
    Value *arglist = v->stack->top();
    v->stack->pop();
    
    std::cout << "IP1:" << v->IP << std::endl;
    v->IP = func->value.funcValue;
    std::cout << "IP2:" << v->IP << std::endl;
    if (!is_list(arglist)) {
        std::cout << "arglist is not a list.:" << std::endl;
        exit(6);
    }
    std::vector<void*> *Env = new std::vector<void*>;
    
    if(func->Env->size() > 0){
        Value *last = (Value *)func->Env->at(func->Env->size()-1);
        if(is_nil(last)){
            last->type=varList;
            last->value.listValue = arglist->value.listValue;
        }
        for (size_t i =0; i < func->Env->size(); i ++) {
            Env->push_back(func->Env->at(i));        
        }
    }
    v->environment = Env;
    v->environment->push_back(list_value(arglist));

}

void ins_dum(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    v->environment->push_back(make_nil());
}

void ins_rec(void *vm) {
    std::cout << "REC." << std::endl;
    SecdVm *v = (SecdVm *) vm;
    Value *func = v->stack->top();
    if (!is_lambda(func)) {
        std::cout << "dap lambda error type:" << func->type << std::endl;
        exit(7);
    }
    v->stack->pop();
    Value *arglist = v->stack->top();
    v->stack->pop();
    v->IP = func->value.funcValue;
    std::cout << "IP2:" << v->IP << std::endl;
    //v->dump->push(d);
    if (!is_list(arglist)) {
        std::cout << "arglist is not a list.:" << std::endl;
        exit(6);
    }
    if(arglist->value.listValue->size() > 0){
        Value *tmp = (Value *)v->environment->at(v->environment->size() - 1);
        for (size_t i =0; i < arglist->value.listValue->size(); i ++) {
            tmp->value.listValue->assign(i,arglist->value.listValue->at(i));
        }
    }
    //v->environment = Env;
    //v->environment->push_back(list_value(arglist));

}

void ins_ld(void *vm) {
    SecdVm *v = (SecdVm *) vm;
    int level = *((int *) (v->code + v->IP));
    v->IP += sizeof (int);
    int position = *((int *) (v->code + v->IP));
    v->IP += sizeof (int);
    Value *tmp = v->lookup_local(level, position);
    if (tmp == NULL) {
        std::cout << "LD error." << std::endl;
        exit(4);
    }
    v->stack->push(tmp);
}

SecdVm::SecdVm() {
    globalEnv = new std::map<std::string, Value*>;
    environment = new std::vector<void*>;
    stack = new std::stack<Value*>;
    dump = new std::stack<DumpItem*>;
    IP = 0;
    code = NULL;
    regist_instruction(I_add, ins_add);
    regist_instruction(I_mul, ins_mul);
    regist_instruction(I_ldi, ins_ldi);
    regist_instruction(I_nil, ins_nil);
    regist_instruction(I_cons, ins_cons);
    regist_instruction(I_ldf, ins_ldf);
    regist_instruction(I_rtn, ins_rtn);
    regist_instruction(I_ap, ins_ap);
    regist_instruction(I_ld, ins_ld);
    regist_instruction(I_def, ins_def);
    regist_instruction(I_sel, ins_sel);
    regist_instruction(I_join, ins_join);
    regist_instruction(I_eq, ins_eq);
    regist_instruction(I_gt, ins_gt);
    regist_instruction(I_lt, ins_lt);
    regist_instruction(I_ge, ins_ge);
    regist_instruction(I_le, ins_le);
    regist_instruction(I_dum, ins_dum);
    regist_instruction(I_rap, ins_rap);
    regist_instruction(I_tap, ins_tap);
    regist_instruction(I_rec, ins_rec);
}

SecdVm::~SecdVm() {
    delete globalEnv;
    delete environment;
    delete stack;
    delete dump;
}

void SecdVm::regist_instruction(short instruction, ins_func func) {
    instructions[instruction] = func;
}

void SecdVm::regist_global_val(char* name, c_func func) {
    std::string n = name;
    globalEnv->insert(std::pair<std::string, Value*>(n, make_cfunc(func)));
}

Value* SecdVm::lookup_global(char* name) {
    std::string n = name;
    std::map<std::string, Value*>::iterator item;
    item = globalEnv->find(n);
    return item->second;
}

Value* SecdVm::lookup_local(int level, int position) {
    int size = environment->size();
    if (level >= size) {
        return NULL;
    }
    level = size - level - 1;
    std::vector<Value*> *tmp = (std::vector<Value*> *)environment->at(level);
    if (tmp == NULL) {
        return NULL;
    }
    size = tmp->size();
    std::cout << "env local size:" << size << std::endl;
    if (position >= size) {
        return NULL;
    }
    return tmp->at(position);
}

void SecdVm::load_binary(char *code, long len) {
    int ret = parse_binary(code, len);
    if (ret == -1) {
        std::cout << "binary load failed." << std::endl;
        exit(1);
    }
}

int SecdVm::parse_binary(char *bin, int slen) {
    char *sign = (char *) malloc(5);
    memset(sign, 0, 5);
    memcpy(sign, bin, 4);
    if (strcmp(sign, "secd") != 0) {
        std::cout << "secd sign error." << std::endl;
        std::cout << "sign:" << bin << std::endl;
        std::cout << "sign[0]:" << (int) sign[0] << std::endl;
        return -1;
    }
    int len = -1;
    int position = -1;

    len = *((int *) (bin + strlen(sign)));
    position = *((int *) (bin + strlen(sign) + sizeof (int)));
    int codelen = slen - strlen(sign) - sizeof (int)*2;
    code = (char *) malloc(codelen);
    memcpy(code, bin + strlen(sign) + sizeof (int)*2, codelen);
    free(sign);
    return 0;
}

void SecdVm::run() {
    short instruction = 0;
    while (1) {
        instruction = *((short *) (code + IP));
        IP += sizeof (short);
        std::cout << "instuction:" << instruction << std::endl;
        if (instruction == I_stop) {
            std::cout << "stop." << std::endl;
            break;
        } else {
            ins_func func = instructions[instruction];
            if (func == NULL) {
                std::cout << "wrong instruct:" << instruction << std::endl;
                exit(8);
            }
            func(this);
        }
    }
}
